/*
 * Copyright (C) 2003 by Dave J. Andruczyk <djandruczyk at yahoo dot com>
 *
 * Linux Megasquirt tuning software
 * 
 * 
 * This software comes under the GPL (GNU Public License)
 * You may freely copy,distribute etc. this as long as the source code
 * is made available for FREE.
 * 
 * No warranty is made or implied. You use this program at your own risk.
 
 
 
 	This code was borrowed from Dave and heavily chopped by Ryan Higgins for use with the Heart of Gold
 
 
 */

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/poll.h>
#include <sys/stat.h>
//#include <termios.h>
#include <unistd.h>
#include "serialio.h"
#define FALSE 0; 
#define TRUE 1;



//struct Serial_Params serial_params;
int connected;
speed_t BAUDRATE = B9600;

       
void open_serial(int tty_num)
{
	fprintf(stderr, "starting open_serial\n");

	int result = -1;
	//char *tmpbuf;
	char devicename[12];	/* temporary unix name of the serial port */

	serial_params.comm_port = tty_num; 

	// Unix port names = /dev/ttyS0 where zero is the port name 
	sprintf(devicename,"/dev/ttyS%i", tty_num);//concatenate string with port number for the name
	// Open Read/Write and NOT as the controlling TTY 
	result = open(devicename , O_RDWR | O_NOCTTY /*| O_NDELAY*/);

	if (result >= 0)
	{
		// SUCCESS 
		// NO Errors occurred opening the port 
		serial_params.open = TRUE;
		serial_params.fd = result;
		// Save serial port status 
		tcgetattr(serial_params.fd,&serial_params.oldtio);
		fprintf(stderr,"ttyS%i Opened Successfully\n",tty_num);
		//update message needs sent to gui here
		//free(tmpbuf);
	}
	else
	{
		// FAILURE 
		// An Error occurred opening the port 
		serial_params.open = FALSE;
		fprintf(stderr,"Error Opening ttyS%i Error Code: %s\n", tty_num,strerror(errno));
		//update message needs sent to gui here
		//free(tmpbuf);
	}

	//free(devicename);

	return;
}
	
int setup_serial_params()
{
	/* Sets up serial port for the modes we want to use. 
	 * NOTE: Original serial tio params are stored and restored 
	 * in the open_serial() and close_serial() functions.
	 */ 

	/*clear struct for new settings*/
	memset(&serial_params.newtio, 0, sizeof(serial_params.newtio)); 
	/* 
	 * BAUDRATE: Set bps rate. You could also use cfsetispeed and 
	 * cfsetospeed
	 * CRTSCTS : output hardware flow control (only used if the cable has
	 * all necessary lines. See sect. 7 of Serial-HOWTO)
	 * CS8     : 8n1 (8bit,no parity,1 stopbit)
	 * CLOCAL  : local connection, no modem contol
	 * CREAD   : enable receiving characters
	 */

	/* Set baud (posix way) */
	cfsetispeed(&serial_params.newtio, BAUDRATE);
	cfsetospeed(&serial_params.newtio, BAUDRATE);

	/* Set additional flags, note |= syntax.. */
	serial_params.newtio.c_cflag |= CLOCAL | CREAD;
	/* Mask and set to 8N1 mode... */
	serial_params.newtio.c_cflag &= ~PARENB;
	serial_params.newtio.c_cflag &= ~CSTOPB;
	serial_params.newtio.c_cflag &= ~CSIZE;
	serial_params.newtio.c_cflag |= CS8;

	/* Disable hardware flow control */
	//serial_params->newtio.c_cflag &= ~CNEW_RTS_CTS;
	

	/* RAW Input */
	serial_params.newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

	/* Disable software flow control */
	serial_params.newtio.c_iflag &= ~(IXON | IXOFF );
	
	/* Set raw output */
	serial_params.newtio.c_oflag &= ~OPOST;

	cfmakeraw(&serial_params.newtio);

	/* 
	   initialize all control characters 
	   default values can be found in /usr/include/termios.h, and are given
	   in the comments, but we don't need them here
	 */
	serial_params.newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */
	serial_params.newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
	serial_params.newtio.c_cc[VERASE]   = 0;     /* del */
	serial_params.newtio.c_cc[VKILL]    = 0;     /* @ */
	serial_params.newtio.c_cc[VEOF]     = 0;     /* Ctrl-d */
	serial_params.newtio.c_cc[VEOL]     = 0;     /* '\0' */
	serial_params.newtio.c_cc[VEOL2]    = 0;     /* '\0' */
	serial_params.newtio.c_cc[VMIN]     = 1;     /* blocking read until 1 character arrives */
	serial_params.newtio.c_cc[VTIME]    = 0;     /* inter-character timer unused */

	tcflush(serial_params.fd, TCIOFLUSH);
	tcsetattr(serial_params.fd,TCSANOW,&serial_params.newtio);

	/* No hurt in checking to see if the MS is present, if it is
	 * It'll update the serial status log, and set the "Connected" flag
	 * which is visible in the Runtime screen 
	 */
	//check_ecu_comms();

	return 0;
}

void close_serial()
{
	//char *tmpbuf;

	tcsetattr(serial_params.fd,TCSANOW,&serial_params.oldtio);
	close(serial_params.fd);
	serial_params.open = FALSE;
	connected = FALSE;
	fprintf(stderr, "COM Port Closed\n");
	//tmpbuf needs sent to gui
	//free(tmpbuf);
}

int check_ecu_comms()
{
	int tmp;
	int res;
	struct pollfd ufds;
	char buf[1024];
	static int locked;
	char *tmpbuf;
	int numRead = 0;
	int i;
	if (locked)
		return 0;
	else
		locked = TRUE;
	/* If port isn't opened no sense trying here... */
	if(serial_params.open)
	{
		ufds.fd = serial_params.fd;
		ufds.events = POLLIN;
		/* save state */
		tmp = serial_params.newtio.c_cc[VMIN];
		serial_params.newtio.c_cc[VMIN]     = 1; /*wait for 1 char */
		tcflush(serial_params.fd, TCIOFLUSH);
		tcsetattr(serial_params.fd,TCSANOW,&serial_params.newtio);

		/* request one batch of realtime vars */
		res = write(serial_params.fd,"A",1);
		fprintf(stderr, "results of wrting to serial %d\n", res);
//		res = poll (&ufds,1,serial_params.poll_timeout);
		res = poll (&ufds,1,100);

		fprintf(stderr, "results of polling %d\n", res);
		if (res)
		{
			/* Command succeeded,  but we still need to drain the
			 * buffer...
			 */
//			while (poll(&ufds,1,serial_params.poll_timeout))
//				res = read(serial_params.fd,&buf,64);
			while (poll(&ufds,1,100)){
				res = read(serial_params.fd,&buf,64);
				numRead += res;
			}
			for(i = 0; i < numRead; ++i) fprintf(stderr, "%c", buf[i]);
			fprintf(stderr, "\n");

			fprintf(stderr, "ECU Comms Test Successfull\n");
			/* COMMS test succeeded */
			//update gui with tmpbuf
			//free(tmpbuf);
			connected = TRUE;
		}
		else
		{
			fprintf(stderr, "I/O with MegaSquirt Timeout\n");
			/* An I/O Error occurred with the MegaSquirt ECU */
			//free(tmpbuf);
			connected = FALSE;
		}

		serial_params.newtio.c_cc[VMIN]     = tmp; /*restore original*/
		tcflush(serial_params.fd, TCIOFLUSH);
		tcsetattr(serial_params.fd,TCSANOW,&serial_params.newtio);
	}
	else
	{
		fprintf(stderr, "Serial Port NOT Opened, Can NOT Test ECU Communications\n");
		/* Serial port not opened, can't test */
		//send tmpbuf to gui as message
		//free(tmpbuf);
	}
	locked = FALSE;
	return (connected);

}
/*
int main(){
	char* message[1024];
	int red = 0;	
	fprintf(stderr, "running\n");
	open_serial(0);
	fprintf(stderr, "serial opened\n");
	setup_serial_params();
	fprintf(stderr, "serial params set\n");

	write(serial_params.fd, "V", 1);

	do{	
     	red = read(serial_params.fd, message, 1024);

	fprintf(stderr, "%s\n",message);
	}while (red != 0);

	close_serial();	
}
*/
